#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

#import "CGSInternal.h"

#define X @"x"
#define Y @"y"
#define WIDTH @"width"
#define HEIGHT @"height"
#define APPLICATION @"application"
#define TITLE @"title"

int main (int argc, const char * argv[]) 
{
	if (argc < 2)
	{
		fprintf (stderr, "No output file provided");
		return 0;
	}
		
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	NSMutableArray * windows = [NSMutableArray array];

	CFStringRef titleQuery = CFStringCreateWithCStringNoCopy (NULL, "kCGSWindowTitle", kCFStringEncodingMacRoman, kCFAllocatorNull);

	CGSConnectionID cid = _CGSDefaultConnection ();
	
	unsigned int workspace = 0;
	
	CGSGetWorkspace (cid, &workspace);
	
	int count = 256;
	int * list = malloc (sizeof(int) * count);
	int outCount = 0;
	
	CGSGetWorkspaceWindowList (cid, workspace, count, list, &outCount);

	int i = 0;
	for (i = 0; i < outCount; i++)
	{
		CGRect cgrect;
		
		CGSGetScreenRectForWindow (cid, list[i], &cgrect);
		
		NSMutableDictionary * window = [NSMutableDictionary dictionary];
		
		[window setValue:[NSNumber numberWithFloat:cgrect.origin.x] forKey:X];
		[window setValue:[NSNumber numberWithFloat:cgrect.origin.y] forKey:Y];
		[window setValue:[NSNumber numberWithFloat:cgrect.size.width] forKey:WIDTH];
		[window setValue:[NSNumber numberWithFloat:cgrect.size.height] forKey:HEIGHT];

		// Title
		
		CFTypeRef titleVal;
		
		CGSGetWindowProperty (cid, list[i], titleQuery, &titleVal);
		
		if (titleVal) 
		{
			NSString * title = (NSString *)  ((CFStringRef) titleVal);
			
			[window setValue:title forKey:TITLE];
		}
		
		// Application information

		CGSConnectionID owner;
		
		CGSGetWindowOwner (cid, list[i], &owner);
		
		pid_t pid = 0;
		CGSConnectionGetPID (owner, &pid);
		ProcessSerialNumber psn = {0};
		GetProcessForPID (pid, &psn);
		
		CFStringRef name = NULL;
		CopyProcessName (&psn, &name);

		NSString * appName = (NSString *) name;
		
		if (name == NULL) 
			appName = @"Unknown Application";

		[window setValue:appName forKey:APPLICATION];
		
		[windows addObject:window];
	}

	NSXMLDocument * xml = [[NSXMLDocument alloc] initWithXMLString:@"<screen />" options:0 error:NULL];
	
	NSXMLElement * root = [xml rootElement];
	
	[root addAttribute:[NSXMLNode attributeWithName:@"date" stringValue:[[NSDate date] description]]];
	
	NSScreen * mainScreen = [NSScreen mainScreen];
	NSRect screenFrame = [mainScreen frame];

	[root addAttribute:[NSXMLNode attributeWithName:@"width" stringValue:[NSString stringWithFormat:@"%.0f", screenFrame.size.width]]];
	[root addAttribute:[NSXMLNode attributeWithName:@"height" stringValue:[NSString stringWithFormat:@"%.0f", screenFrame.size.height]]];

	for (NSDictionary * window in windows)
	{
		NSXMLElement * windowElement = [[NSXMLElement alloc] initWithName:@"window"];
		
		for (NSString * att in [window allKeys])
		{
			NSObject * value = [window valueForKey:att];
			
			[windowElement addAttribute:[NSXMLNode attributeWithName:att stringValue:[value description]]];
		}
		
		[root addChild:windowElement];
		
		[windowElement release];
	}

	NSString * path = [[NSString stringWithCString:argv[1]] stringByStandardizingPath];
	
	if (![[xml XMLData] writeToFile:path atomically:YES])
		fprintf (stderr, "Error writing file %s", argv[1]);
	
	[xml release];
	
    [pool drain];
    return 0;
}
